/*
    This file is part of QTau
    Copyright (C) 2013-2018  Tobias "Tomoko" Platen <tplaten@posteo.de>
    Copyright (C) 2013       digited       <https://github.com/digited>
    Copyright (C) 2010-2013  HAL@ShurabaP  <https://github.com/haruneko>

    QTau is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    SPDX-License-Identifier: GPL-3.0+
*/

#include "midifile.h"
#include <QJsonArray>
#include <smf.h>
#include "math.h"
#include <QJsonObject>
#include "ustjkeys.h"

MidiFile::MidiFile()
{

}

int MidiFile::saveMidi(const QJsonArray& ust,QString fileName)
{
    //FIXME: ustJson(ust);

    smf_t *smf;
    smf_track_t *track;
    smf_event_t *event;

    smf = smf_new();

    track = smf_track_new();
    smf_add_track(smf, track);

    int bpm = 60;
    //int bpm = getTempo();
    track = smf_track_new();
    smf_add_track(smf, track);
    char temposig[6];
    int tempo=60*1000*1000/bpm;
    temposig[0] = 0xFF;
    temposig[1] = 0x51;
    temposig[2] = 0x03;
    temposig[3] = (tempo >> 16) & 0xFF;
    temposig[4] = (tempo >> 8) & 0xFF;
    temposig[5] = (tempo) & 0xFF;
    event = smf_event_new_from_pointer(temposig, 6);
    smf_track_add_event_pulses(track,event,0);
    char timesig[7];
    timesig[0] = 0xFF;
    timesig[1] = 0x58;
    timesig[2] = 0x04;
    //QJsonArray a = getTimeSignature();
    //int nn=a[0].toInt();
    //int dd=a[1].toInt();
    int nn = 4;
    int dd = 4;
    dd = log(dd)/log(2);
    timesig[3] = nn;
    timesig[4] = dd;
    timesig[5] = 0;
    timesig[6] = 8;
    event = smf_event_new_from_pointer(timesig, 7);
    smf_track_add_event_pulses(track,event,0);

    for (int i = 0; i < ust.count(); ++i)
    {
        auto o = ust[i];


        double ts = 0.25;

        unsigned char midi[3];
        midi[0]=0x90;
        midi[1]=o.toObject()[NOTE_KEY_NUMBER].toInt();
        midi[2]=100;//FIXME do not hardcode

        int noteOffset = o.toObject()[NOTE_PULSE_OFFSET].toInt();
        int noteLength = o.toObject()[NOTE_PULSE_LENGTH].toInt();

        if(noteLength>0)
        {

        event = smf_event_new_from_pointer(midi, 3);
        smf_track_add_event_pulses(track,event,ts*noteOffset);

        //http://www.ccarh.org/courses/253/handout/smf/

        QString lyric = o.toObject()[NOTE_LYRIC].toString();

        event = smf_event_new_textual(0x05,lyric.toUtf8());



        smf_track_add_event_pulses(track,event,ts*noteOffset);
        midi[0]=0x80;
        event = smf_event_new_from_pointer(midi, 3);
        smf_track_add_event_pulses(track,event,ts*(noteOffset+noteLength));


        }



    }

    return smf_save(smf, fileName.toUtf8());


}

void MidiFile::loadMidi(QString fileName,QJsonArray& ustRef)
{
    smf_t *smf;
    smf_event_t *event;
    smf = smf_load(fileName.toUtf8());

    if(smf==NULL) return;

    smf_tempo_t* tempo = smf_get_tempo_by_pulses(smf,0);

    QJsonArray ts;
    ts.append(tempo->numerator);
    ts.append(tempo->denominator);
    //setTimeSignature(ts);
    float bpm=tempo->microseconds_per_quarter_note/(1000.0*1000.0);
    bpm=60.0/bpm;

    //setTempo(round(bpm));



    smf_track_t *track = smf_get_track_by_number(smf, smf->number_of_tracks);
    int activeNote = -1;
    int notePos = 0;

    QString text;



    for(int i=1;i<track->number_of_events+1;i++)
    {
        event = smf_track_get_event_by_number(track, i);
        if(smf_event_is_textual(event)){
            char* txt = smf_event_extract_text(event);
            text = txt;
            free(txt);
        }
        else
        {
            if(event->midi_buffer_length==3)
            {
                unsigned char status=event->midi_buffer[0];
                unsigned char statusb = 0xF0 & status;
                unsigned char notenum=event->midi_buffer[1];
                unsigned char velocity=event->midi_buffer[2];

                float factor=1;

                if(statusb == 0x80 || (statusb == 0x90 && velocity==0) )
                {
                    //qDebug()<< "note off " <<notenum << " " <<velocity;

                    int length = (event->time_pulses-notePos);
                    QJsonObject note;
                    //qDebug() << notePos << "::" << length;
                    note[NOTE_PULSE_OFFSET]= notePos*factor;
                    note[NOTE_PULSE_LENGTH]= length*factor;
                    note[NOTE_KEY_NUMBER] = activeNote;
                    note[NOTE_VELOCITY]=velocity;
                    if(text.length()==0) text="[[a]]";
                    note[NOTE_LYRIC] = text;
                    ustRef.append(note);
                    activeNote = -1;
                }
                else
                    if(statusb == 0x90)
                    {
                        if(activeNote!=-1) {
                            smf_delete(smf);
                            return;
                        }
                        //qDebug() << "note on " << notenum;
                        activeNote = notenum;
                        notePos = event->time_pulses;
                    }
            }
        }
    }

    smf_delete(smf);
}
